{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Overfitting Design Pattern\n",
    "\n",
    "The *Overfitting design pattern* refers to situations where overfitting is beneficial. In this notebook, we'll use overfitting on a batch as a way to gut check our ML model. \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll start by building our model and tf.data pipeline as usual."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import tensorflow as tf\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "from tensorflow import keras\n",
    "from tensorflow import feature_column as fc\n",
    "from tensorflow.keras import layers, models, Model\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_csv(\"./data/babyweight_train.csv\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Set up the features for the model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# prepare inputs\n",
    "df.is_male = df.is_male.astype(str)\n",
    "\n",
    "df.mother_race.fillna(0, inplace = True)\n",
    "df.mother_race = df.mother_race.astype(str)\n",
    "\n",
    "FEATURES = ['is_male', 'mother_age', 'plurality', 'gestation_weeks', 'mother_race']\n",
    "LABEL = ['weight_pounds']\n",
    "\n",
    "N_TRAIN = int(df.shape[0] * 0.80)\n",
    "\n",
    "X_train = df[FEATURES][:N_TRAIN]\n",
    "X_valid = df[FEATURES][N_TRAIN:]\n",
    "\n",
    "\n",
    "y_train = df[LABEL][:N_TRAIN]\n",
    "y_valid = df[LABEL][N_TRAIN:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create the input pipeline."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# train/validation dataset\n",
    "trainds = tf.data.Dataset.from_tensor_slices((X_train.to_dict('list'), y_train.values))\n",
    "evalds = tf.data.Dataset.from_tensor_slices((X_valid.to_dict('list'), y_valid.values))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "({'is_male': <tf.Tensor: shape=(), dtype=string, numpy=b'False'>, 'mother_age': <tf.Tensor: shape=(), dtype=int32, numpy=12>, 'plurality': <tf.Tensor: shape=(), dtype=string, numpy=b'Single(1)'>, 'gestation_weeks': <tf.Tensor: shape=(), dtype=int32, numpy=40>, 'mother_race': <tf.Tensor: shape=(), dtype=string, numpy=b'1.0'>}, <tf.Tensor: shape=(1,), dtype=float64, numpy=array([7.74924851])>)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Examine the datasets.\n",
    "for dict_slice in trainds.take(1):\n",
    "        print(\"{}\\n\".format(dict_slice))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Set up the feature columns for the model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# create feature columns to handle categorical variables\n",
    "numeric_columns = [fc.numeric_column(\"mother_age\"),\n",
    "                  fc.numeric_column(\"gestation_weeks\")]\n",
    "\n",
    "CATEGORIES = {\n",
    "    'plurality': list(df.plurality.unique()),\n",
    "    'is_male' : list(df.is_male.unique()),\n",
    "    'mother_race': list(df.mother_race.unique())\n",
    "}\n",
    "\n",
    "categorical_columns = []\n",
    "for feature, vocab in CATEGORIES.items():\n",
    "    cat_col = fc.categorical_column_with_vocabulary_list(\n",
    "        key=feature, vocabulary_list=vocab, dtype=tf.string)\n",
    "    categorical_columns.append(fc.indicator_column(cat_col))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we build the model, a simple neural network."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /opt/conda/lib/python3.7/site-packages/tensorflow_core/python/feature_column/feature_column_v2.py:4267: IndicatorColumn._variable_shape (from tensorflow.python.feature_column.feature_column_v2) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "The old _FeatureColumn APIs are being deprecated. Please use the new FeatureColumn APIs instead.\n",
      "WARNING:tensorflow:From /opt/conda/lib/python3.7/site-packages/tensorflow_core/python/feature_column/feature_column_v2.py:4322: VocabularyListCategoricalColumn._num_buckets (from tensorflow.python.feature_column.feature_column_v2) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "The old _FeatureColumn APIs are being deprecated. Please use the new FeatureColumn APIs instead.\n"
     ]
    }
   ],
   "source": [
    "# create Inputs for model\n",
    "inputs = {colname: tf.keras.layers.Input(\n",
    "    name=colname, shape=(), dtype=\"float32\")\n",
    "    for colname in [\"mother_age\", \"gestation_weeks\"]}\n",
    "inputs.update({colname: tf.keras.layers.Input(\n",
    "    name=colname, shape=(), dtype=tf.string)\n",
    "    for colname in [\"plurality\", \"is_male\", \"mother_race\"]})\n",
    "\n",
    "# build DenseFeatures for the model\n",
    "dnn_inputs = layers.DenseFeatures(categorical_columns+numeric_columns)(inputs)\n",
    "\n",
    "# create hidden layers\n",
    "h1 = layers.Dense(20, activation=\"relu\")(dnn_inputs)\n",
    "h2 = layers.Dense(10, activation=\"relu\")(h1)\n",
    "\n",
    "# create model\n",
    "output = layers.Dense(1, activation=\"relu\")(h2)\n",
    "model = tf.keras.models.Model(inputs=inputs, outputs=output)\n",
    "model.compile(optimizer='adam',\n",
    "              loss=tf.keras.losses.MeanSquaredError(),\n",
    "              metrics=['mse'])   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Overfit on a batch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can inspect our train data pipeline by pulling a singe batch of 5 examples. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'babyweight': [[7.74924851]\n",
      " [7.56185559]\n",
      " [7.18706974]\n",
      " [6.37576862]\n",
      " [7.93664143]]\n",
      "features:\n",
      "  'is_male'           : [b'False' b'True' b'False' b'True' b'False']\n",
      "  'mother_age'        : [12 12 12 12 12]\n",
      "  'plurality'         : [b'Single(1)' b'Single(1)' b'Single(1)' b'Single(1)' b'Single(1)']\n",
      "  'gestation_weeks'   : [40 40 34 36 35]\n",
      "  'mother_race'       : [b'1.0' b'2.0' b'3.0' b'2.0' b'0.0']\n"
     ]
    }
   ],
   "source": [
    "for feature_batch, label_batch in trainds.batch(5).take(1):\n",
    "    print(\"'babyweight': {}\".format(label_batch))\n",
    "    print(\"features:\")\n",
    "    for key, value in feature_batch.items():\n",
    "      print(\"  {!r:20s}: {}\".format(key, value))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For training, we'll take a larger batch and call it `single_batch`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "BATCH_SIZE = 256\n",
    "\n",
    "single_batch = trainds.batch(BATCH_SIZE).take(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then we train the model on the single batch. Note we must use `.repeat()` since we'll quickly run out of data training on just a single batch. Also, we've set the number of training examples to BATCH_SIZE."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "# train the classifcation model\n",
    "tf.random.set_seed(33)\n",
    "\n",
    "NUM_TRAINING_EXAMPLES = BATCH_SIZE  # total number of training examples\n",
    "NUM_VALID_EXAMPLES = X_valid.shape[0]\n",
    "NUM_EPOCHS = 100\n",
    "TOTAL_TRAINING_EXAMPLES = int(NUM_EPOCHS * NUM_TRAINING_EXAMPLES)\n",
    "\n",
    "steps_per_epoch = (TOTAL_TRAINING_EXAMPLES // (BATCH_SIZE * NUM_EPOCHS))\n",
    "\n",
    "evalds = evalds.batch(X_valid.shape[0]).take(int(NUM_VALID_EXAMPLES//BATCH_SIZE))\n",
    "\n",
    "# train the model\n",
    "history = model.fit(single_batch.repeat(),\n",
    "                    validation_data=evalds, \n",
    "                    epochs=NUM_EPOCHS,\n",
    "                    steps_per_epoch=steps_per_epoch,\n",
    "                    verbose=0\n",
    "                   )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lastly, we'll plot the validation and train loss curves. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_curves(history, metrics):\n",
    "    nrows = 1\n",
    "    ncols = 2\n",
    "    fig = plt.figure(figsize=(10, 5))\n",
    "\n",
    "    for idx, key in enumerate(metrics):  \n",
    "        ax = fig.add_subplot(nrows, ncols, idx+1)\n",
    "        plt.plot(history.history[key])\n",
    "        plt.plot(history.history['val_{}'.format(key)])\n",
    "        plt.title('model {}'.format(key))\n",
    "        plt.ylabel(key)\n",
    "        plt.xlabel('epoch')\n",
    "        plt.legend(['train', 'validation'], loc='upper left');"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_curves(history, ['loss'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Copyright 2020 Google Inc. Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
